//
//  HZCachingURLCache.m
//  app
//
//  Created by 刘华舟 on 15/5/28.
//  Copyright (c) 2015年 hdaren. All rights reserved.
//

#import "HZCachingURLCache.h"
#import <CommonCrypto/CommonDigest.h>

@implementation HZCachingURLCache

- (void)removeCachedResponseForRequest:(NSURLRequest *)request {
    NSLog(@"removeCachedResponseForRequest:%@", request.URL.absoluteString);
    [_cachedResponses removeObjectForKey:request.URL.absoluteString];
    [super removeCachedResponseForRequest:request];
}

- (void)removeAllCachedResponses {
    NSLog(@"removeAllObjects");
    [_cachedResponses removeAllObjects];
    [super removeAllCachedResponses];
}


static NSString *cacheDirectory;
static NSSet *supportSchemes;

+ (void)initialize {
    NSString *cachesPath = [NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject], @"kangxihui.web.cache"];
    
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:cachesPath isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) )
    {
        [fileManager createDirectoryAtPath:cachesPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    cacheDirectory = cachesPath;
    supportSchemes = [NSSet setWithObjects:@"http", @"https", @"ftp", nil];
}

- (void)saveInfo {
    if ([self.responsesInfo count]) {
        NSString *path = [cacheDirectory stringByAppendingPathComponent:@"responsesInfo.plist"];
        [self.responsesInfo writeToFile:path atomically:YES];
    }
}

- (void)clearInfo{
    self.responsesInfo = [[NSMutableDictionary alloc] init];
    self.cachedResponses = [[NSMutableDictionary alloc] init];
}

- (id)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(NSString *)path {
    if (self = [super initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:path]) {
        self.cachedResponses = [[NSMutableDictionary alloc] init];
        NSString *path = [cacheDirectory stringByAppendingPathComponent:@"responsesInfo.plist"];
        NSFileManager *fileManager = [[NSFileManager alloc] init];
        if ([fileManager fileExistsAtPath:path]) {
            self.responsesInfo = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
        } else {
            self.responsesInfo = [[NSMutableDictionary alloc] init];
        }
    }
    return self;
}


- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request{
    if ([request.HTTPMethod compare:@"GET"] != NSOrderedSame) {
        return [super cachedResponseForRequest:request];
    }
    
    NSURL *url = request.URL;
    if (![supportSchemes containsObject:url.scheme]) {
        return [super cachedResponseForRequest:request];
    }
    
    
    NSString *absoluteString = url.absoluteString;
    NSLog(@"%@", absoluteString);
    NSCachedURLResponse *cachedResponse = [_cachedResponses objectForKey:absoluteString];
    if (cachedResponse) {
        NSLog(@"cached: %@", absoluteString);
        return cachedResponse;
    }
    
    NSDictionary *responseInfo = [_responsesInfo objectForKey:absoluteString];
    if (responseInfo) {
        NSString *path = [cacheDirectory stringByAppendingString:[responseInfo objectForKey:@"filename"]];
        NSFileManager *fileManager = [[NSFileManager alloc] init];
        if ([fileManager fileExistsAtPath:path]) {
            
            NSData *data = [NSData dataWithContentsOfFile:path];
            NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[responseInfo objectForKey:@"MIMEType"] expectedContentLength:data.length textEncodingName:nil];
            cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
            
            [self.cachedResponses setObject:cachedResponse forKey:absoluteString];
            NSLog(@"cached: %@", absoluteString);
            return cachedResponse;
        }
    }
    
    NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:request.timeoutInterval];
    newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
    newRequest.HTTPShouldHandleCookies = request.HTTPShouldHandleCookies;
    
    NSError *error = nil;
    NSURLResponse *response = nil;
    NSData *data = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
    if (error) {
        NSLog(@"%@", error);
        NSLog(@"not cached: %@", absoluteString);
        return nil;
    }
    
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(data.bytes, data.length, digest);
    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x", digest[i]];
    
    NSString *filename = output;//sha1([absoluteString UTF8String]);
    NSString *path = [cacheDirectory stringByAppendingString:filename];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    [fileManager createFileAtPath:path contents:data attributes:nil];
    
    NSURLResponse *newResponse = [[NSURLResponse alloc] initWithURL:response.URL MIMEType:response.MIMEType expectedContentLength:data.length textEncodingName:nil];
    responseInfo = [NSDictionary dictionaryWithObjectsAndKeys:filename, @"filename", newResponse.MIMEType, @"MIMEType", nil];
    [self.responsesInfo setObject:responseInfo forKey:absoluteString];
    
    
    cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:newResponse data:data];
    [self.cachedResponses setObject:cachedResponse forKey:absoluteString];
    return cachedResponse;
    
}

@end
